
from bcat.error import InvalidArgumentError
from enum import Enum
from collections import deque
class EventQueue:
    class OperationEvent:
        class Operation(Enum):
            Register = 0
            Unregister = 1

            @staticmethod
            def valid(op):
                return op in (EventQueue.OperationEvent.Operation.Register, 
                    EventQueue.OperationEvent.Operation.Unregister)

            @staticmethod
            def is_register(op):
                return EventQueue.OperationEvent.Operation.Register == op

            @staticmethod
            def is_unregister(op):
                return EventQueue.OperationEvent.Operation.Unregister == op

        def __init__(self, op, event):
            self.__op = op
            self.__event = event

        def operation(self):
            return self.__op
        def event(self):
            return self.__event

        def is_register(self):
            return EventQueue.OperationEvent.Operation.is_register(self.__op)
        def is_unregister(self):
            return EventQueue.OperationEvent.Operation.is_unregister(self.__op)

    def __init__(self):
        self.__queue = deque()
        
    def push_back_register(self, event):
        self.__queue.append(EventQueue.OperationEvent(EventQueue.OperationEvent.Operation.Register, event)) 

    def push_back_unregister(self, event):
        self.__queue.append(EventQueue.OperationEvent(EventQueue.OperationEvent.Operation.Unregister, event)) 

    def push_back(self, op, event):
        if EventQueue.OperationEvent.Operation.valid(op):
            self.__queue.append(EventQueue.OperationEvent(op, event)) 
        else:
            raise InvalidArgumentError("error operation:{} of event:{}".format(op, str(event)), 1)

    def pop_front(self):
        op_e = self.__queue.popleft()
        return (op_e.operation(), op_e.event())

    def __len__(self):
        return len(self.__queue)

    def empty(self):
        return len(self.__queue) == 0

    def clear(self):
        self.__queue.clear()

from event import Event, TimeoutEvent
from event_creator import EventCreator
import unittest
class TestEventQueue(unittest.TestCase):
    def test_main(self):
        q = EventQueue()
        self.assertEqual(0, len(q))
        self.assertTrue(q.empty())

        e = EventCreator.from_timeout(100, None)
        q.push_back_register(e)
        self.assertEqual(1, len(q))

        (op, new_e) = q.pop_front()
        self.assertTrue(new_e == e and EventQueue.OperationEvent.Operation.is_register(op))
        self.assertTrue(q.empty())

        q.push_back(EventQueue.OperationEvent.Operation.Register, e)
        self.assertEqual(1, len(q))
        (op, new_e) = q.pop_front()
        self.assertTrue(new_e == e and EventQueue.OperationEvent.Operation.is_register(op))
        

if __name__ == "__main__":
    unittest.main(verbosity=2)
